using System;
using System.Linq;
using System.Xml.Linq;
using Coderoom.ScrumPlanner.Data.Contracts;
using Coderoom.ScrumPlanner.Domain;
using Coderoom.ScrumPlanner.Utilities;

namespace Coderoom.ScrumPlanner.Data.Repositories.Xml
{
	public sealed class XmlThemeRepository : XmlRepository, IThemeRepository
	{
		public override string DataFileName
		{
			get { return "Themes.xml"; }
		}

		#region IThemeRepository Members

		public ThemeCollection GetThemes(Guid projectId)
		{
			Lock.EnterReadLock();

			try
			{
				var result = GetThemesInternal().Where(theme => theme.ProjectId == projectId).ToArray();
				return new ThemeCollection(result);
			}
			finally
			{
				Lock.ExitReadLock();
			}
		}

		public Theme GetTheme(Guid themeId)
		{
			Lock.EnterReadLock();

			try
			{
				return GetThemesInternal().Where(theme => theme.Id == themeId).SingleOrDefault();
			}
			finally
			{
				Lock.ExitReadLock();
			}
		}

		public void CreateTheme(Theme theme)
		{
			Lock.EnterWriteLock();

			try
			{
				theme.Id = Guid.NewGuid();

				var themeData = ReadXml();
				// ReSharper disable PossibleNullReferenceException
				themeData.Root.Add(new XElement("Theme", new XAttribute("id", theme.Id), new XAttribute("projectId", theme.ProjectId), new XElement("Title", theme.Title), new XElement("Slug", theme.Slug)));
				// ReSharper restore PossibleNullReferenceException
				WriteXml(themeData);
			}
			finally
			{
				Lock.ExitWriteLock();
			}
		}

		public bool DeleteTheme(Guid themeId)
		{
			Lock.EnterWriteLock();

			try
			{
				var themeData = ReadXml();

				var themeToDelete = themeData.ImmediateDescendants("Theme").Where(theme => theme.ReadAttributeAsGuid("id") == themeId).SingleOrDefault();

				if (themeToDelete != null)
				{
					themeToDelete.Remove(); // removes it from parent
					WriteXml(themeData);
					return true;
				}

				return false;
			}
			finally
			{
				Lock.ExitWriteLock();
			}
		}

		#endregion

		private IQueryable<Theme> GetThemesInternal()
		{
			var themeData = ReadXml();

			return (from theme in themeData.ImmediateDescendants("Theme")
			        select new Theme {Id = theme.ReadAttributeAsGuid("id"), ProjectId = theme.ReadAttributeAsGuid("projectId"), Title = theme.ReadChildValue("Title"), Slug = theme.ReadChildValue("Slug")}).AsQueryable();
		}
	}
}